package com.alibaba.aliper.agent.jmeter;

public class ThreadGroupData {
	private int interval;
	public ThreadGroupData(String threadName,int interval){
		this.name = threadName;
		this.interval = interval;
	}
	public ThreadGroupData(String threadName,int reportInterval,ThreadGroupData thisData) {
		this(threadName,reportInterval);
		this.merge(thisData);
	}
	private String name = null;
	private long lastParseTime=System.currentTimeMillis();
	private Long minTime=null;
	private Long maxTime=null;
	private Long minResponse = null;
	private Long maxResponse = null;
	private Long earlierTime = null;
	private Long closerTime = null;
	public double getTPS() {
		if(this.closerTime == null || this.earlierTime == null || this.closerTime == this.earlierTime)
			return 0;
		return this.count * 1000 / (this.closerTime - this.earlierTime);
	}
	public double getAvgResponse() {
		return sum/count;
	}
	public String getName() {
		return name;
	}
	private long count = 0;
	private double sum = 0;
	private long failed = 0;
	public long getLastParseTime() {
		return lastParseTime;
	}
	private void setLastParseTime(Long lastParseTime) {
		this.lastParseTime = lastParseTime;
	}
	public Long getMinTime() {
		return minTime;
	}
	public Long getMaxTime() {
		return maxTime;
	}
	public Long getMinResponse() {
		return minResponse;
	}
	public Long getMaxResponse() {
		return maxResponse;
	}
	private void checkResponseAndTime(Long time,Long response) {
		if(response == null)
			return;
		if(this.minResponse == null || response < this.minResponse){
			this.minResponse = response;
			this.minTime = time;
		}
		if(this.maxResponse == null || response > this.maxResponse){
			this.maxResponse = response;
			this.maxTime = time;
		}
		if(this.earlierTime == null || time < this.earlierTime){
			this.earlierTime = time;
		}
		if(this.closerTime == null || time > this.closerTime){
			this.closerTime = time;
		}
		
	}
	public long getCount() {
		return count;
	}
	public double getSum() {
		return sum;
	}
	private void increaseCount() {
		this.count++;
	}
	private void increaseSum(long amount) {
		this.sum += amount;
	}
	private void increaseFailed(){
		this.failed++;
	}
	public double getFailedRate() {
		return (failed / (double)count)*100;
	}
	private Long lastSampleTime = null;
	private ThreadGroupData sample = null;
	
	public synchronized ThreadGroupData update(long time, boolean success, long response) {
		ThreadGroupData ret = null;
		if(this.interval > 0){
			if(this.lastSampleTime == null || time - this.lastSampleTime > this.interval){
				this.lastSampleTime = time;
				ret = this.sample;
				this.sample = new ThreadGroupData(this.name,this.interval);
			}
			update(this.sample, time,success, response);
		}
		update(this, time,success, response);
		return ret;
	}
	private static void update(ThreadGroupData data,long time,boolean success,long response){
		data.setLastParseTime(System.currentTimeMillis());
		if(!success){
			data.increaseFailed();
		}
		data.checkResponseAndTime(time, response);
		data.increaseCount();
		data.increaseSum(response);
	}
	public void merge(ThreadGroupData thisData) {
		if(thisData == null)
			return;
		this.checkResponseAndTime(thisData.minTime, thisData.minResponse);
		this.checkResponseAndTime(thisData.maxTime, thisData.maxResponse);
		this.count += thisData.count;
		this.sum += thisData.sum;
		this.failed += thisData.failed;
		if(this.lastParseTime < thisData.lastParseTime)
			this.lastParseTime = thisData.lastParseTime;
	}
	public Long getEarlierTime() {
		return earlierTime;
	}
	public Long getCloserTime() {
		return closerTime;
	}
	public ThreadGroupData pack() {
		if(this.closerTime != null &&  this.lastSampleTime != null){
			if(this.closerTime > this.lastSampleTime){
				return this.sample;
			}
		}
		return null;
	}
	
}
